﻿using BaseDll;
using System;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Text.Unicode;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames;
using Image = System.Windows.Controls.Image;

namespace DisplayReadingClientWpf
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// 
        /// </summary>
        TcpClient tcpClient { get; set; }
        /// <summary>
        /// 是否初始化
        /// </summary>
        private bool isIni { get; set; }

        /// <summary>
        /// 配置
        /// </summary>
        public ComData config { get; set; }
        /// <summary>
        /// 为每一个切片创建一个UDP套接字
        /// </summary>
        UdpClient[] udpServer;
        /// <summary>
        /// 
        /// </summary>
        Image[] images;

        int tcpport = 10001;

        int mode = 1;
        // 开启数据接收线程
        Bitmap[] bitmaps = null;
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            tcpClient = new TcpClient();
            Task.Factory.StartNew(Heart);
            Task.Factory.StartNew(Receive);
            //Console.Title = "接收";
        }

        private void Receive()
        {
            while (true)
            {
                if (tcpClient.Connected)
                {
                    var data = tcpClient.GetStream();
                    byte[] bytes = new byte[1024];
                    data.Read(bytes, 0, bytes.Length);
                    var dstdata = UTF8Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    var dst = JsonHelp.ToObj<ComData>(dstdata);
                    if (dst.com == EnumCom.ini)
                    {
                        config = dst;
                        isIni = true;
                        if (mode == 0)
                        {
                            SetUi();
                        }
                        if (mode == 1)
                        {
                            SetUi2();
                        }

                        Task.Factory.StartNew(IniSocket);
                    }
                    Console.WriteLine(dstdata);
                }
                Thread.Sleep(200);
            }
        }

        private void SetUi()
        {
            this.Dispatcher.Invoke(() =>
            {
                images = new Image[config.dataCount];
                for (int i = 0; i < config.dataCount; i++)
                {
                    ui.RowDefinitions.Add(new RowDefinition()
                    {
                        Height = new GridLength(1, GridUnitType.Star)
                    });
                    Image image = new Image();
                    image.Stretch = Stretch.Fill;
                    ui.Children.Add(image);
                    Grid.SetRow(image, i);
                    images[i] = image;
                }

            });
        }
        Image image;
        private void SetUi2()
        {
            this.Dispatcher.Invoke(() =>
            {
                image = new Image();
                image.Stretch = Stretch.Fill;
                ui.Children.Add(image);
            });
            bitmaps = new Bitmap[config.dataCount];
        }

        private void IniSocket()
        {
            udpServer = new UdpClient[config.dataCount];
            for (int i = 0; i < config.dataCount; i++)
            {
                int port = tcpport + i + 1;
                IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), config.startPort + i);
                // 创建套接字
                udpServer[i] = new UdpClient(endpoint);
            }

            while (true)
            {
                Parallel.For(0, udpServer.Length, i =>
                {
                    if (udpServer[i].Available > 0)
                    {
                        EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                        //IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), reveiveport);
                        // 设置一个64k的字节数组作为缓存
                        byte[] data = new byte[65536];
                        var dst = udpServer[i].Client.ReceiveFrom(data, ref remoteEndPoint);
                        //string receivedData = Encoding.UTF8.GetString(data);
                        //Console.WriteLine($"接收端口:{((System.Net.IPEndPoint)remoteEndPoint).Port}+ {receivedData}");

                        if (mode == 0)
                        {
                            SetImage(i, data);
                        }
                        if (mode == 1)
                        {
                            MemoryStream ms = new MemoryStream(data, 0, data.Length);
                            bitmaps[i] = new Bitmap(ms);
                        }
                    }
                });

                if (mode == 1)
                {
                    SetImage2(bitmaps);
                    GC.Collect();   
                }

                Thread.Sleep(20);
            }
        }

        private void SetImage2(Bitmap[] bitmaps)
        {
            int width = 0;
            int height = 0;

            foreach (var bitmap in bitmaps)
            {
                if (bitmap == null)
                {
                    continue;
                }
                height += bitmap.Height;
                width = bitmap.Width;
            }
            if (width==0||height==0)
            {
                return;
            }
            Bitmap bit = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(bit))
            {
                height = 0;
                for (Int32 i = 0; i < bitmaps.Length; i++)
                {
                    if (bitmaps[i] == null)
                    {
                        continue;
                    }
                    g.DrawImage(bitmaps[i], 0, height, bitmaps[i].Width, bitmaps[i].Height);
                    height += bitmaps[i].Height;
                }
            }
            image.Dispatcher.Invoke(() =>
            {
                var data = BitmapToImageSource(bit);
                image.Source = data.Item1;
            });
        }
        public Tuple<BitmapImage, byte[]> BitmapToImageSource(Bitmap bitmap)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                // Save the bitmap to the memory stream
                bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
                memoryStream.Position = 0;

                // Create a BitmapImage and initialize it with the memory stream
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memoryStream;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();

                // Freeze the BitmapImage for better performance
                bitmapImage.Freeze();
                byte[] bytes = new byte[memoryStream.Length];
                memoryStream.Read(bytes, 0, bytes.Length);

                return Tuple.Create(bitmapImage, bytes);
            }
        }
        private void SetImage(int index, byte[] data)
        {
            images[index].Dispatcher.Invoke(() =>
            {
                MemoryStream ms = new MemoryStream(data, 0, data.Length);
                // 将图像显示到对应的PictureBox控件上
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = ms;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad; // 加载到内存中
                bitmapImage.EndInit();
                images[index].Source = bitmapImage;
            });
        }

        private void Heart()
        {
            while (true)
            {
                if (tcpClient.Connected)
                {
                    ComData comData = new ComData()
                    {
                        com = EnumCom.ini,
                    };
                    if (isIni)
                    {
                        comData.com = EnumCom.heart;
                    }
                    var senddata = JsonHelp.ToString(comData);
                    var databyte = UTF8Encoding.UTF8.GetBytes(senddata);
                    tcpClient.Client.Send(databyte);
                }
                else
                {
                    tcpClient.Connect(IPAddress.Parse("127.0.0.1"), tcpport);
                }
                Thread.Sleep(1000);
            }
        }
    }
}